package com.extract.runner;

import com.extract.sys.entity.TaskRecord;
import com.extract.sys.service.ITaskRecordService;
import com.extract.task.basic.ITask;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

/**
 * @author: chenfenghai
 * @version: 1.0
 * @date: 2020-10-14 15:00
 */
@Slf4j
@Component
public class TaskRecordRunner {

    /** 应用上下文 */
    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    @Autowired
    ITaskRecordService taskRecordService;

    private static final String KEY_FORMAT_STRING = "_";
    private static final Map<String, ScheduledFuture<?>> SCHEDULED_FUTURE_MAP = new ConcurrentHashMap<>();

    private Map<String, ITask> taskMap;

    @PostConstruct
    public void init() {
        taskMap = applicationContext.getBeansOfType(ITask.class);
    }

    private ITask getTask(String taskCode) {
        if(taskMap == null || taskMap.isEmpty()){
            return null;
        }
        return taskMap.get(taskCode);
    }

    public void startTaskRecord(){
        List<TaskRecord> taskRecordList = taskRecordService.list();
        taskRecordList.parallelStream().forEach(this::buildScheduler);
    }

    private void buildScheduler(TaskRecord taskRecord) {
        String key = StringUtils.joinWith(KEY_FORMAT_STRING,
                StringUtils.trimToEmpty(taskRecord.getTenantId()),
                StringUtils.trimToEmpty(taskRecord.getCinemaCode()),
                StringUtils.trimToEmpty(taskRecord.getSystemCode()),
                StringUtils.trimToEmpty(taskRecord.getTaskCode()));
        ITask task = getTask(StringUtils.trimToEmpty(taskRecord.getTaskCode()).toUpperCase());
        if(Objects.isNull(task)){
            log.error("找不到对应的任务对象：{}", key);
            // 更新任务记录
            LocalDateTime now = LocalDateTime.now();
            taskRecord.setUpdateTime(now);
            taskRecord.setLastFailureTime(now);
            taskRecordService.updateById(taskRecord);
            return;
        }
        ScheduledFuture<?> future = SCHEDULED_FUTURE_MAP.get(key);
        if(Objects.nonNull(future)){
            return;
        }
        Runnable taskRunnable = () -> task.execute(taskRecord);
        Trigger trigger = new CronTrigger(taskRecord.getTimeCron());
        future = threadPoolTaskScheduler.schedule(taskRunnable, trigger);
        SCHEDULED_FUTURE_MAP.putIfAbsent(key, future);
    }
}
